package com.example.helloandroidworld;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.app.SherlockFragment;
import com.android.future.usb.UsbAccessory;
import com.android.future.usb.UsbManager;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.OverlayItem;
import com.example.helloandroidworld.ProximityIntentReceiver;
import com.example.helloandroidworld.MainActivity.GeoUpdateHandler;
import com.example.helloandroidworld.R;
import com.example.helloandroidworld.MyOverlays;
//import com.google.api.services.tasks.model.Tasks;

import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.fusiontables.Fusiontables;
import com.google.api.services.fusiontables.FusiontablesScopes;
/*import com.google.api.services.samples.tasks.android.AsyncLoadTasks;
import com.google.api.services.samples.tasks.android.MainActivity;
import com.google.api.services.samples.tasks.android.R;
*/

import android.accounts.AccountManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ToggleButton;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import android.view.View;


import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;


public class MainActivity extends SherlockFragmentActivity
{ 
	
	private static final String TAG2 = "ArduinoAccessory";
	 
	private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION";
 
	private UsbManager mUsbManager;
	private PendingIntent mPermissionIntent;
	private boolean mPermissionRequestPending;
	private ToggleButton buttonLED;
 
	UsbAccessory mAccessory;
	ParcelFileDescriptor mFileDescriptor;
	FileInputStream mInputStream;
	FileOutputStream mOutputStream;
	
	 MapView myMap;
	 MyLocationOverlay myLocation;
	 MyOverlays itemizedoverlay;
	 Criteria accuracy;
	 
	 private LocationManager locationManager;
	 private static final Level LOGGING_LEVEL = Level.OFF;
	 private static final String PREF_ACCOUNT_NAME = "accountName";
	 static final String TAG = "TasksSample";
	 static final int REQUEST_GOOGLE_PLAY_SERVICES = 0;
	 static final int REQUEST_AUTHORIZATION = 1;
	 static final int REQUEST_ACCOUNT_PICKER = 2;
	 final HttpTransport transport = AndroidHttp.newCompatibleTransport();
	 final JsonFactory jsonFactory = new GsonFactory();
	 private static final String PROX_ALERT_INTENT =  "com.example.helloandroidworld.ProximityAlert";
	 GoogleAccountCredential credential;
	 List<String> locationsList;
	 List<String> availableList;
	 List<String> nameList;
	 List<String> numbersList;
	 String rowid;
	 int lat, lng;
	 int status;
	 
	 
	 ArrayAdapter<String> adapter;
	 String[] available = {"Free", "Class", "Meeting"};
	 
	 com.google.api.services.fusiontables.Fusiontables service;
	 int numAsyncTasks;
	 private ListView listView;
	 
	 
	 private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				String action = intent.getAction();
				if (ACTION_USB_PERMISSION.equals(action)) {
					synchronized (this) {
						UsbAccessory accessory = UsbManager.getAccessory(intent);
						if (intent.getBooleanExtra(
								UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
							openAccessory(accessory);
						} else {
							Log.d(TAG2, "permission denied for accessory "
									+ accessory);
						}
						mPermissionRequestPending = false;
					}
				} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
					UsbAccessory accessory = UsbManager.getAccessory(intent);
					if (accessory != null && accessory.equals(mAccessory)) {
						closeAccessory();
					}
				}
			}
		};
	 
	
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState); 
        
        // if onCreate is being called for the first time, savedInstanceState bundle is null
        // thus it is set to the default index, which is 1. or home.
         // enable logging
        Logger.getLogger("com.google.api.client").setLevel(LOGGING_LEVEL);
        // Google Accounts
        credential = GoogleAccountCredential.usingOAuth2(this, FusiontablesScopes.FUSIONTABLES);
        SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
        credential.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
        // Tasks client
        service = new com.google.api.services.fusiontables.Fusiontables.Builder(transport, jsonFactory, credential).setApplicationName("Google-FusionsAndroidSample/1.0").build();
     
        
        int index = 0;
        if(savedInstanceState != null)
        {
        	// gets the currently selected tab index and stores it in index
        	index = savedInstanceState.getInt("ActionIndex");
        }

       myMap = new MapView(this, "0b2e0oo_Zf_ksp9cZHEFxpBjcCCS_3IH2r7uQdg");
       locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
       accuracy = new Criteria();
       accuracy.setAccuracy(Criteria.ACCURACY_MEDIUM);
       locationManager.requestLocationUpdates(locationManager.getBestProvider(accuracy, true), 300000, 0, new GeoUpdateHandler());       
       myLocation = new MyLocationOverlay(this, myMap);
       myMap.getOverlays().add(myLocation);
       myMap.postInvalidate();       
       Drawable drawable = this.getResources().getDrawable(R.drawable.point);
       itemizedoverlay = new MyOverlays(this, drawable);
       //refreshView();
       
       // add tabs
        addTabs(index);
        showDialog(this);
        
        mUsbManager = UsbManager.getInstance(this);
		mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
		IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
		filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
		registerReceiver(mUsbReceiver, filter);
 
		if (getLastNonConfigurationInstance() != null) {
			mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
			openAccessory(mAccessory);
		}
 
		//setContentView(R.layout.main);
		//buttonLED = (ToggleButton) findViewById(R.id.toggleButtonLED);
		}
        

    
    public void onResume()
    {
    	super.onResume();
    	
    	myLocation.enableMyLocation();
    	myLocation.enableCompass();
	    if (checkGooglePlayServicesAvailable()) {
		      haveGooglePlayServices();
		    }
	    
	    if (mInputStream != null && mOutputStream != null) {
			return;
		}
 
		UsbAccessory[] accessories = mUsbManager.getAccessoryList();
		UsbAccessory accessory = (accessories == null ? null : accessories[0]);
		if (accessory != null) {
			if (mUsbManager.hasPermission(accessory)) {
				openAccessory(accessory);
			} else {
				synchronized (mUsbReceiver) {
					if (!mPermissionRequestPending) {
						mUsbManager.requestPermission(accessory,mPermissionIntent);
						mPermissionRequestPending = true;
					}
				}
			}
		} else {
			Log.d(TAG2, "mAccessory is null");
		}
	}
	
    
    
    public AlertDialog myAlertDialog;

    public void showDialog(Context context) {
            if( myAlertDialog != null && myAlertDialog.isShowing() ) return;

            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle("Availability");
            builder.setItems(available, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        status = which;
                    }});
            builder.setCancelable(false);
            myAlertDialog = builder.create();
            myAlertDialog.show();

    }
    
    public void onPause()
    {
    	super.onPause();
    	myLocation.disableMyLocation();
    	myLocation.disableCompass();
    	closeAccessory();
    }
    
    @Override
    public void onSaveInstanceState( Bundle saveInstanceState)
    {
    	// saves current tab during configuration changes.
    	// so it can be set properly when onCreate is called again
    	super.onSaveInstanceState(saveInstanceState);
    	int Index = this.getSupportActionBar().getSelectedNavigationIndex();
    	saveInstanceState.putInt("ActionIndex", Index); 	// stores the index in the bundle saveInstanceState
    	// which is passed to onCreate()
    }
    
    // a lot of tab stuff
    // creates the tabs and adds them to the actionbar
    public void addTabs(int index)
    {
        // tab browsing stuff
        ActionBar action = getSupportActionBar();
        action.setNavigationMode( ActionBar.NAVIGATION_MODE_TABS);
        action.setDisplayShowTitleEnabled(true);
        action.setHomeButtonEnabled(true);
        action.setDisplayShowHomeEnabled(true);
        
        Tab tab = action.newTab()
        		.setText(R.string.SchedulerFragment)
        		.setTabListener( new MyTabListener<SchedulerFragment>( this, "SchedulerFragment",  SchedulerFragment.class) );
        action.addTab(tab,false); // stores a tab and does not select a default tab
         
        tab = action.newTab()
        		.setText(R.string.MapFragment)
        		.setTabListener( new MyTabListener<MapFragment>( this, "MapFragment", MapFragment.class) );
        action.addTab(tab,false);// stores a tab and does not select a default tab
        
        tab = action.newTab()
        		.setText(R.string.MessagingFragment)
        		.setTabListener( new MyTabListener<Messaging>( this, "Messaging", Messaging.class) );
        action.addTab(tab,false);// stores a tab and does not select a default tab
        action.setSelectedNavigationItem(index); // selects the appropiate tab by the index
    	
    }
    // sets the listener up
	private static class MyTabListener<T extends SherlockFragment> implements ActionBar.TabListener
	{ 

		private Fragment mFragment; 
		private final SherlockFragmentActivity mActivity;
		private final String mTag;
	    private final Class<T> mClass;
		
		public MyTabListener( SherlockFragmentActivity activity, String tag, Class<T> clz )
		{
			mActivity = activity;
			mTag = tag;	
			mClass = clz;
			// the fragment might already exist. such as during a configuration change
			// returns null otherwise.
			mFragment = activity.getSupportFragmentManager().findFragmentByTag(tag);
		}
		
		@Override
		public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft) 
		{
			// is fragment initialized?
			if( mFragment == null)
			{
				// else, instantiate
				 mFragment = Fragment.instantiate(mActivity, mClass.getName());
				 // attaches tab. does multiple things in one line!
				 mActivity.getSupportFragmentManager().beginTransaction().add(android.R.id.content, mFragment, mTag).commit();
			}
			else
			{
				//simply attach it
				if( mFragment.isDetached() )
				{
					// attaches tab. does multiple things in one line!
					mActivity.getSupportFragmentManager().beginTransaction().attach(mFragment).commit();
				}
			}
		}
		
		@Override
		public void onTabUnselected(Tab tab, android.support.v4.app.FragmentTransaction ft) 
		{
	        if (mFragment != null) 
	        {
	            // Detach the fragment, because another one is being attached
	        	mActivity.getSupportFragmentManager().beginTransaction().detach(mFragment).commit();
	        }
		}

		@Override
		public void onTabReselected(Tab tab, android.support.v4.app.FragmentTransaction ft) {/* do nothing*/}		
	}  



	  void showGooglePlayServicesAvailabilityErrorDialog(final int connectionStatusCode) {
		    runOnUiThread(new Runnable() {
		      public void run() {
		        Dialog dialog =
		            GooglePlayServicesUtil.getErrorDialog(connectionStatusCode, MainActivity.this,
		                REQUEST_GOOGLE_PLAY_SERVICES);
		        dialog.show();
		      }
		    });
		  }

	  void refreshView() {
		  
	       for (int i=0;  i < locationsList.size(); i++)
	       {
	       String X = locationsList.get(i).substring(0, 8);
	       String Y = locationsList.get(i).substring(9,18);
	       int Lat = Integer.parseInt(X);
	       int Lon = Integer.parseInt(Y);
	       GeoPoint p = new GeoPoint(Lat, Lon);
	       OverlayItem overlayitem = new OverlayItem(p, nameList.get(i), availableList.get(i));
	       itemizedoverlay.addOverlay(overlayitem);
	       myMap.getOverlays().add(itemizedoverlay);
	       addProximityAlert(Lat, Lon);
	       }	       

	  blinkLED();
	  }


		  @Override
		  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		    super.onActivityResult(requestCode, resultCode, data);
		    switch (requestCode) {
		      case REQUEST_GOOGLE_PLAY_SERVICES:
		        if (resultCode == Activity.RESULT_OK) {
		          haveGooglePlayServices();
		        } else {
		          checkGooglePlayServicesAvailable();
		        }
		        break;
		      case REQUEST_AUTHORIZATION:
		        if (resultCode == Activity.RESULT_OK) {
		          //AsyncLoadTasks.run(this);
		        } else {
		          chooseAccount();
		        }
		        break;
		      case REQUEST_ACCOUNT_PICKER:
		        if (resultCode == Activity.RESULT_OK && data != null && data.getExtras() != null) {
		          String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
		          if (accountName != null) {
		            credential.setSelectedAccountName(accountName);
		            SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
		            SharedPreferences.Editor editor = settings.edit();
		            editor.putString(PREF_ACCOUNT_NAME, accountName);
		            editor.commit();
		            //AsyncLoadTasks.run(this);
		          }
		        }
		        break;
		    }
		  }
/*
		  @Override
		  public boolean onCreateOptionsMenu(Menu menu) {
		    MenuInflater inflater = getMenuInflater();
		    inflater.inflate(R.menu.main_menu, menu);
		    return super.onCreateOptionsMenu(menu);
		  }

		  @Override
		  public boolean onOptionsItemSelected(MenuItem item) {
		    switch (item.getItemId()) {
		      case R.id.menu_refresh:
		        AsyncLoadTasks.run(this);
		        break;
		      case R.id.menu_accounts:
		        chooseAccount();
		        return true;
		    }
		    return super.onOptionsItemSelected(item);
		  }

		  /** Check that Google Play services APK is installed and up to date. */
		  private boolean checkGooglePlayServicesAvailable() {
		    final int connectionStatusCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
		    if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
		      showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
		      return false;
		    }
		    return true;
		  }

		  private void haveGooglePlayServices() {
		    // check if there is already an account selected
		    if (credential.getSelectedAccountName() == null) {
		      // ask user to choose account
		      chooseAccount();
		    } else {
		      // load calendars
		      //AsyncLoadTasks.run(this);
		    }
		  }

		  private void chooseAccount() {
		    startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
		  }

		  public class GeoUpdateHandler implements LocationListener {

		    @Override
		    public void onLocationChanged(Location location) {
		      AsyncLoadTasks.run(MainActivity.this);
		          }

		    @Override
		    public void onProviderDisabled(String provider) {
		    }

		    @Override
		    public void onProviderEnabled(String provider) {
		    }

		    @Override
		    public void onStatusChanged(String provider, int status, Bundle extras) {
		    }
		  }
		  
		  private void addProximityAlert(int alat, int alon) {
			  
				Intent intent = new Intent(PROX_ALERT_INTENT);
				PendingIntent proximityIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
				  
				locationManager.addProximityAlert((double) (alat / 1e6),((double) (alon / 1e6)) , 2000f, 30000, proximityIntent); // will be used to generate an Intent to fire when entry to or exit from the alert region is detected

				IntentFilter filter = new IntentFilter(PROX_ALERT_INTENT); 
				registerReceiver(new ProximityIntentReceiver(), filter);

				
			  	}
		  
		  private void openAccessory(UsbAccessory accessory) {
				mFileDescriptor = mUsbManager.openAccessory(accessory);
				if (mFileDescriptor != null) {
					mAccessory = accessory;
					FileDescriptor fd = mFileDescriptor.getFileDescriptor();
					mInputStream = new FileInputStream(fd);
					mOutputStream = new FileOutputStream(fd);
					Log.d(TAG2, "accessory opened");
				} else {
					Log.d(TAG2, "accessory open fail");
				}
			}
		 
		 
			private void closeAccessory() {
				try {
					if (mFileDescriptor != null) {
						mFileDescriptor.close();
					}
				} catch (IOException e) {
				} finally {
					mFileDescriptor = null;
					mAccessory = null;
				}
			}
		 
			public void blinkLED(){
		 
				byte[] buffer = new byte[1];
		 

					buffer[0]=(byte)1; // button says off, light is on
		 
				if (mOutputStream != null) {
					try {
						mOutputStream.write(buffer);
					} catch (IOException e) {
						Log.e(TAG2, "write failed", e);
					}
				}
			}		  
}